package com.oa.service.impl;

import com.oa.mapper.DeptMapper;
import com.oa.mapper.LeaveMapper;
import com.oa.mapper.ProcessConfigMapper;
import com.oa.mapper.UserMapper;
import com.oa.pojo.Leave;
import com.oa.pojo.PageBean;
import com.oa.pojo.ProcessConfig;
import com.oa.service.LeaveService;
import com.oa.utils.CommonUtil;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author Str
 * @Date 2021/12/7 9:19
 * @Description :
 */
@Service
public class LeaveServiceImpl implements LeaveService {
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private LeaveMapper leaveMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ProcessConfigMapper proConfigMapper;

    // 工作流相关service
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RuntimeService runtimeService;

    @Override
    public String getDeptLeaderID(String deptId) {
        return deptMapper.getDeptLeaderID(deptId);
    }

    @Override
    public String getHigherLevelDeptId(String deptId) {
        String pids = deptMapper.getPids(deptId);
        // 分割pids
        String[] split = pids.split(",");
        // 获取最后那个部门ID，也就是上一级的部门ID
        return split[split.length - 1];
    }

    @Override
    public String getHigherLevelDeptLeaderId(String deptId) {
        String pids = deptMapper.getPids(deptId);
        // 分割pids
        String[] split = pids.split(",");
        // 获取上级部门ID
        String higherLevelDeptId = split[split.length - 1];
        // 获取上级部门领导ID
        return deptMapper.getDeptLeaderID(higherLevelDeptId);
    }

    @Override
    public int updateAssigneeAndTask(String insId, String taskId, String assignee) {
        int count = leaveMapper.updateAssigneeAndTask(insId, taskId, assignee);
        return count;
    }

    /*--------------------- [A.发起申请业务] ----------------------------*/
    //{a.1}包装流程变量..
    private Map<String, Object> setVariables(Leave leave) {
        Map<String, Object> vars = new HashMap<>();
        vars.put("inputUser", leave.getInitiator()); //发起人
        vars.put("startDate", CommonUtil.dateToString(leave.getStartDate())); //开始日期
        vars.put("endDate", CommonUtil.dateToString(leave.getEndDate())); //结束日期
        vars.put("reason", leave.getReason()); //请假原因
        vars.put("days", leave.getDays());    //请假天数
        vars.put("leaveType", leave.getLeaveType()); //请假类型
        vars.put("cancel", "false");  //取消任务
        return vars;
    }

    /**
     * a.2-提交申请
     * initiator：发起人
     * insID：流程实例ID
     *
     * @return void
     */
    private void commitLeave(String initiator, String insID) {
        //{1}查询任务 ID
        Task task = taskService.createTaskQuery()
                .taskAssignee(initiator)
                .processInstanceId(insID)
                .singleResult();
        System.out.println("task.getId():" + task.getId());
        //{2}提交任务..
        taskService.complete(task.getId());
    }

    //a.3-开启流程与提交申请
    @Override
    public void startProcess(Leave leave) throws ParseException {
        //{1}计算天数
        int days = CommonUtil.daysBetween(leave.getStartDate(), leave.getEndDate());
        leave.setDays(days);  //设置天数.
        //{2}包装流程变量
        Map<String, Object> procVars = setVariables(leave);
        //{3}查询系统的流程字典表 - 流程定义 ID
        ProcessConfig config = proConfigMapper.getProcConfigByCategory("请假流程");
        String procDefId = config.getProcDefId();
        //{4}开启流程实例(存入流程变量)
        ProcessInstance instance = runtimeService.startProcessInstanceById(procDefId, procVars);
        System.out.println("procDefId:" + procDefId + ",procVars:" + procVars);
        //{5}补全 leave 信息
        //如: 流程定义ID, 流程实例ID, 创建时间, status
        leave.setProcDefId(procDefId);
        leave.setProcInstId(instance.getId());
        leave.setCreateTime(CommonUtil.dateToString(new Date()));
        leave.setStatus("办理中");
        System.out.println("startProcess.leave:" + leave);


        //{6}保存到 t_leave 表
        leaveMapper.addLeave(leave);

        //{7}提交任务 [发起人,流程实例ID]
        commitLeave(leave.getInitiator(), instance.getId());
    }

    /*--------------------- [B.查询我发起的业务(现有的)] ---------------------*/
    @Override
    public PageBean<Leave> queryMyInitiate(String assignee) {
        //{1}省略分页功能..
        //{2}获取到列表
        List<Leave> list = leaveMapper.queryMyInitiate(assignee);
        PageBean<Leave> pageBean = new PageBean<Leave>();
        //{3}临时设置。。(到时要设置总记录数)
        pageBean.setCount(list.size());
        pageBean.setList(list);
        //{3}返回到上层
        return pageBean;
    }

    /*--------------------- [B.查询我已审核的业务(现有的)] ---------------------*/
    @Override
    public PageBean<Leave> queryMyReviewed(String assignee) {
        //{1}省略分页功能..
        //{2}获取到列表
        List<Leave> list = leaveMapper.queryMyReviewed(assignee);
        PageBean<Leave> pageBean = new PageBean<Leave>();
        //{3}临时设置。。(到时要设置总记录数)
        pageBean.setCount(list.size());
        pageBean.setList(list);
        //{3}返回到上层
        return pageBean;
    }


    /*--------------------- [C.查询待我审批的任务]-------------------------*/
    @Override
    public PageBean<Leave> queryWaitMyApprove(
            String assigneeId, int page, int limit) {
        //{1}这里暂不设置分页
        List<Leave> list = null;
        PageBean<Leave> pBean = new PageBean<>();
        //{2}查询待我审批的任务清单
        list = leaveMapper.queryWaitMyApprove(assigneeId);
        //{3}封装数据到分页 Bean
        pBean.setCount(list.size());  //暂时先设置 list 大小
        pBean.setList(list);
        return pBean;
    }

    //{C.2}查询待我审批的任务详情
    @Override
    public Leave queryMyTaskByTaskId(String taskId) {
        return leaveMapper.queryMyTaskByTaskId(taskId);
    }

    /*--------------------- [D.查询我已审批的业务]-----------------------*/
	/*
			-------[待定中]--------
	*/


    /*----------------------- [E.审批我的业务] --------------------------*/
    @Override
    public void updateStatusByInstanceId(String procInstId, String status) {
        int count = leaveMapper.updateStatus(procInstId, status);
        if (count == 1) {
            System.out.println("======更新成功=====");
        }
        //----- 暂时不处理更新失败 -----
    }

    /*
     * 前端有4个数据会过来:
     * {a}deptId: 部门ID
     * {b}appFlag: true(同意)/false(不同意)
     * {c}refuseReason: 拒绝原因。
     * {d}taskId: 任务ID
     */
    @Override
    public void completeMyApprove(Map data) {
        String deptId = (String) data.get("deptId");
        String taskId = (String) data.get("taskId");
        String appFlag = (String) data.get("appFlag");

        int days = Integer.parseInt((String) data.get("days"));

        data.put("days", days);
        //{1}我是谁: 老板 / 主管
        //{2}获取更高一级部门 id
//        String higherLevelDeptId = getHigherLevelDeptId(deptId);
        String pids = deptMapper.getPids(deptId);
        // 分割pids
        String[] split = pids.split(",");
        // 获取最后那个部门ID，也就是上一级的部门ID
        String pDeptId = split[split.length - 1];

        if ("top".equals(pDeptId)) { //我是老板 [总经办]
            data.put("bossApp", appFlag); //处理意见
            System.out.println("boss==============================");
        } else {       //我是主管
            data.put("deptApp", appFlag); //处理意见
        }
        System.out.println("=====================");
        for (Object o : data.keySet()) {
            System.out.println(o + ":" + data.get(o));
        }
        System.out.println("=====================");
        //{3}把办理人设置为 null
//        leaveMapper.updateAssigneeByTask(taskId, null);
        printMark("{Service}把办理人设置为 null");
        //{4}提交任务。
        taskService.complete(taskId, data);
    }

    private void printMark(Object obj) {
        System.out.println("+--------------------------------------+");
        System.out.println(obj);
        System.out.println("+--------------------------------------+");
    }
}
